<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <meta name="generator" content="VuePress 2.0.0-beta.61">
    <script>
      (function() {
        const userMode = localStorage.getItem('vuepress-reco-color-scheme') || 'auto';
        const systemDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;

        if (userMode === 'dark' || (userMode === 'auto' && systemDarkMode)) {
          document.documentElement.classList.toggle('dark', true);
        }
      })();
    </script>
    <link rel="icon" href="/icon.png"><title>浏览器渲染原理 | FYJ</title><meta name="description" content="Just playing around">
    <link rel="modulepreload" href="/assets/app-5e55c3a9.js"><link rel="modulepreload" href="/assets/framework-9675d465.js"><link rel="modulepreload" href="/assets/liulanqixuanranyuanli.html-e15be5a7.js"><link rel="modulepreload" href="/assets/liulanqixuanranyuanli.html-3208ecf3.js"><link rel="prefetch" href="/assets/index.html-6d5e9dd3.js" as="script"><link rel="prefetch" href="/assets/index.html-3d8b60b2.js" as="script"><link rel="prefetch" href="/assets/index.html-a7cfb774.js" as="script"><link rel="prefetch" href="/assets/index.html-1a66ce3d.js" as="script"><link rel="prefetch" href="/assets/index.html-a2322c32.js" as="script"><link rel="prefetch" href="/assets/index.html-2b8e88d2.js" as="script"><link rel="prefetch" href="/assets/index.html-36817084.js" as="script"><link rel="prefetch" href="/assets/index.html-c05495db.js" as="script"><link rel="prefetch" href="/assets/index.html-3cf0f594.js" as="script"><link rel="prefetch" href="/assets/index.html-33a8693c.js" as="script"><link rel="prefetch" href="/assets/index.html-80880afd.js" as="script"><link rel="prefetch" href="/assets/index.html-df5b0273.js" as="script"><link rel="prefetch" href="/assets/index.html-d608509e.js" as="script"><link rel="prefetch" href="/assets/index.html-ac9bff28.js" as="script"><link rel="prefetch" href="/assets/index.html-d251d55d.js" as="script"><link rel="prefetch" href="/assets/index.html-d299a2c9.js" as="script"><link rel="prefetch" href="/assets/index.html-c8596e07.js" as="script"><link rel="prefetch" href="/assets/index.html-ce42ac51.js" as="script"><link rel="prefetch" href="/assets/index.html-e1e2c2da.js" as="script"><link rel="prefetch" href="/assets/index.html-49c6b4a8.js" as="script"><link rel="prefetch" href="/assets/index.html-3880c1f3.js" as="script"><link rel="prefetch" href="/assets/index.html-b5b12757.js" as="script"><link rel="prefetch" href="/assets/index.html-6cf06f14.js" as="script"><link rel="prefetch" href="/assets/index.html-1a88d37b.js" as="script"><link rel="prefetch" href="/assets/index.html-c8e98ed0.js" as="script"><link rel="prefetch" href="/assets/index.html-d7cf9c00.js" as="script"><link rel="prefetch" href="/assets/git.html-0da1c675.js" as="script"><link rel="prefetch" href="/assets/html5meitiyuansu.html-4654ddc1.js" as="script"><link rel="prefetch" href="/assets/duoliebuju.html-54f235b4.js" as="script"><link rel="prefetch" href="/assets/DOM__BOM.html-b97d346f.js" as="script"><link rel="prefetch" href="/assets/jsbiji.html-a3fbc3f8.js" as="script"><link rel="prefetch" href="/assets/jsbiji2.html-6c330c31.js" as="script"><link rel="prefetch" href="/assets/RESTheAJAX.html-17e205d8.js" as="script"><link rel="prefetch" href="/assets/shuxingmiaoshufu.html-08b53360.js" as="script"><link rel="prefetch" href="/assets/zhonghuievent-loop.html-7baa2b76.js" as="script"><link rel="prefetch" href="/assets/mongodb.html-ad7d95ea.js" as="script"><link rel="prefetch" href="/assets/mongoose.html-31658686.js" as="script"><link rel="prefetch" href="/assets/express.html-042999ef.js" as="script"><link rel="prefetch" href="/assets/httpxieyi.html-abaf3902.js" as="script"><link rel="prefetch" href="/assets/httpmokuai.html-9408a820.js" as="script"><link rel="prefetch" href="/assets/nodejs.html-8df1574a.js" as="script"><link rel="prefetch" href="/assets/nodejshexinmokuai.html-72c9480b.js" as="script"><link rel="prefetch" href="/assets/promise.html-85e3fffc.js" as="script"><link rel="prefetch" href="/assets/webpackhevite.html-a09bf01e.js" as="script"><link rel="prefetch" href="/assets/huihuakongzhi.html-86d8c25d.js" as="script"><link rel="prefetch" href="/assets/baoguanliqi.html-86b29b9f.js" as="script"><link rel="prefetch" href="/assets/mokuaihua.html-67d4835d.js" as="script"><link rel="prefetch" href="/assets/fangdaolian.html-932412c5.js" as="script"><link rel="prefetch" href="/assets/typescript.html-0bd71496.js" as="script"><link rel="prefetch" href="/assets/vue-router3.html-09f47896.js" as="script"><link rel="prefetch" href="/assets/vue2(2).html-10c04317.js" as="script"><link rel="prefetch" href="/assets/vue2.html-82b6d2df.js" as="script"><link rel="prefetch" href="/assets/vue2zujiantongxin.html-56d49820.js" as="script"><link rel="prefetch" href="/assets/vueRouter3lanjiazaishiyongdewenti.html-3ffca1f7.js" as="script"><link rel="prefetch" href="/assets/Vuex3.html-e24f4da6.js" as="script"><link rel="prefetch" href="/assets/api.html-b73a9946.js" as="script"><link rel="prefetch" href="/assets/home.html-746a4c0d.js" as="script"><link rel="prefetch" href="/assets/plugin.html-6a7b36ed.js" as="script"><link rel="prefetch" href="/assets/theme.html-6037defd.js" as="script"><link rel="prefetch" href="/assets/121501.html-8973c891.js" as="script"><link rel="prefetch" href="/assets/404.html-60b35caa.js" as="script"><link rel="prefetch" href="/assets/index.html-101169bd.js" as="script"><link rel="prefetch" href="/assets/index.html-c05f203a.js" as="script"><link rel="prefetch" href="/assets/index.html-0c6bc7be.js" as="script"><link rel="prefetch" href="/assets/index.html-0fe42912.js" as="script"><link rel="prefetch" href="/assets/index.html-35698f58.js" as="script"><link rel="prefetch" href="/assets/index.html-a9998c9a.js" as="script"><link rel="prefetch" href="/assets/index.html-e03acce1.js" as="script"><link rel="prefetch" href="/assets/index.html-936bfd18.js" as="script"><link rel="prefetch" href="/assets/index.html-3b167d99.js" as="script"><link rel="prefetch" href="/assets/index.html-6a7e33f2.js" as="script"><link rel="prefetch" href="/assets/index.html-00dc6c81.js" as="script"><link rel="prefetch" href="/assets/index.html-c386c5b9.js" as="script"><link rel="prefetch" href="/assets/index.html-62cab89d.js" as="script"><link rel="prefetch" href="/assets/index.html-c6f54c68.js" as="script"><link rel="prefetch" href="/assets/index.html-5fc54677.js" as="script"><link rel="prefetch" href="/assets/index.html-96867bd4.js" as="script"><link rel="prefetch" href="/assets/index.html-452a2070.js" as="script"><link rel="prefetch" href="/assets/index.html-500c2666.js" as="script"><link rel="prefetch" href="/assets/index.html-d797d831.js" as="script"><link rel="prefetch" href="/assets/index.html-84073cb9.js" as="script"><link rel="prefetch" href="/assets/index.html-8dfee4a9.js" as="script"><link rel="prefetch" href="/assets/index.html-a675820e.js" as="script"><link rel="prefetch" href="/assets/index.html-948f048e.js" as="script"><link rel="prefetch" href="/assets/index.html-522daa8a.js" as="script"><link rel="prefetch" href="/assets/index.html-4d67ded2.js" as="script"><link rel="prefetch" href="/assets/index.html-8caf183d.js" as="script"><link rel="prefetch" href="/assets/git.html-9cef5060.js" as="script"><link rel="prefetch" href="/assets/html5meitiyuansu.html-cd096af4.js" as="script"><link rel="prefetch" href="/assets/duoliebuju.html-4e591000.js" as="script"><link rel="prefetch" href="/assets/DOM__BOM.html-518d085e.js" as="script"><link rel="prefetch" href="/assets/jsbiji.html-f1c6b5c4.js" as="script"><link rel="prefetch" href="/assets/jsbiji2.html-0ce3d86b.js" as="script"><link rel="prefetch" href="/assets/RESTheAJAX.html-174a11fd.js" as="script"><link rel="prefetch" href="/assets/shuxingmiaoshufu.html-12f7f1aa.js" as="script"><link rel="prefetch" href="/assets/zhonghuievent-loop.html-993374db.js" as="script"><link rel="prefetch" href="/assets/mongodb.html-06aa4d45.js" as="script"><link rel="prefetch" href="/assets/mongoose.html-f6a2c1e1.js" as="script"><link rel="prefetch" href="/assets/express.html-c34de6a8.js" as="script"><link rel="prefetch" href="/assets/httpxieyi.html-393ba2a3.js" as="script"><link rel="prefetch" href="/assets/httpmokuai.html-84b55eda.js" as="script"><link rel="prefetch" href="/assets/nodejs.html-2ee518f3.js" as="script"><link rel="prefetch" href="/assets/nodejshexinmokuai.html-fabb53b0.js" as="script"><link rel="prefetch" href="/assets/promise.html-34216aec.js" as="script"><link rel="prefetch" href="/assets/webpackhevite.html-aac8da2d.js" as="script"><link rel="prefetch" href="/assets/huihuakongzhi.html-1540a73e.js" as="script"><link rel="prefetch" href="/assets/baoguanliqi.html-d4dece61.js" as="script"><link rel="prefetch" href="/assets/mokuaihua.html-2cfeca4a.js" as="script"><link rel="prefetch" href="/assets/fangdaolian.html-4c95566c.js" as="script"><link rel="prefetch" href="/assets/typescript.html-3e2bf303.js" as="script"><link rel="prefetch" href="/assets/vue-router3.html-fa748c7b.js" as="script"><link rel="prefetch" href="/assets/vue2(2).html-b4107b02.js" as="script"><link rel="prefetch" href="/assets/vue2.html-dfda70b7.js" as="script"><link rel="prefetch" href="/assets/vue2zujiantongxin.html-4cf781c8.js" as="script"><link rel="prefetch" href="/assets/vueRouter3lanjiazaishiyongdewenti.html-a5f191aa.js" as="script"><link rel="prefetch" href="/assets/Vuex3.html-68ef32c1.js" as="script"><link rel="prefetch" href="/assets/api.html-710c8c92.js" as="script"><link rel="prefetch" href="/assets/home.html-b45de374.js" as="script"><link rel="prefetch" href="/assets/plugin.html-2075a048.js" as="script"><link rel="prefetch" href="/assets/theme.html-5b5f0e80.js" as="script"><link rel="prefetch" href="/assets/121501.html-865346dc.js" as="script"><link rel="prefetch" href="/assets/404.html-eab7b035.js" as="script"><link rel="prefetch" href="/assets/reco-valine-a0c1af1f.js" as="script">
    <link rel="preload" href="/assets/style-887583e0.css" as="style"><link rel="stylesheet" href="/assets/style-887583e0.css">
  </head>
  <body>
    <div id="app"><!--[--><div class="theme-container"><div class="common-wrapper series--no show-catalog"><div><header class="navbar-container"><!--[--><div class="site-brand nav-item"><img class="logo" src="/logo.png" alt="FYJ"><a href="/" class="site-name can-hide">FYJ</a></div><div class="nav-item navbar-links-wrapper" style=""><div><form class="search-box" role="search"><input type="search" autocomplete="off" spellcheck="false" value><!----></form></div><nav class="navbar-links"><!--[--><div class="navbar-links__item"><a href="/" class="link router-link-active" aria-label="Home"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->Home<!--]--></span></span><!--[--><!--]--></a></div><div class="navbar-links__item"><a href="/categories/html-note/1/" class="link" aria-label="分类"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->分类<!--]--></span></span><!--[--><!--]--></a></div><div class="navbar-links__item"><a href="/tags/html5/1/" class="link" aria-label="标签"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->标签<!--]--></span></span><!--[--><!--]--></a></div><!--]--></nav><span class="xicon-container btn-toggle-dark-mode btn--dark-mode"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" style="width:20px;height:20px;font-size:20px;color:inherit;"><path d="M15 2h2v3h-2z" fill="currentColor"></path><path d="M27 15h3v2h-3z" fill="currentColor"></path><path d="M15 27h2v3h-2z" fill="currentColor"></path><path d="M2 15h3v2H2z" fill="currentColor"></path><path d="M5.45 6.884l1.414-1.415l2.121 2.122l-1.414 1.414z" fill="currentColor"></path><path d="M23 7.58l2.121-2.12l1.414 1.414l-2.121 2.121z" fill="currentColor"></path><path d="M23.002 24.416l1.415-1.414l2.12 2.122l-1.413 1.414z" fill="currentColor"></path><path d="M5.47 25.13L7.59 23L9 24.42l-2.12 2.12l-1.41-1.41z" fill="currentColor"></path><path d="M16 8a8 8 0 1 0 8 8a8 8 0 0 0-8-8zm0 14a6 6 0 0 1 0-12z" fill="currentColor"></path></svg></span><span class="xicon-container btn-toggle-menus"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" style="width:20px;height:20px;font-size:20px;color:inherit;"><circle cx="16" cy="8" r="2" fill="currentColor"></circle><circle cx="16" cy="16" r="2" fill="currentColor"></circle><circle cx="16" cy="24" r="2" fill="currentColor"></circle></svg></span></div><!--]--></header><div class="mobile-menus-container"><nav class="navbar-links mobile"><!--[--><div class="navbar-links__item"><a href="/" class="link router-link-active" aria-label="Home"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->Home<!--]--></span></span><!--[--><!--]--></a></div><div class="navbar-links__item"><a href="/categories/html-note/1/" class="link" aria-label="分类"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->分类<!--]--></span></span><!--[--><!--]--></a></div><div class="navbar-links__item"><a href="/tags/html5/1/" class="link" aria-label="标签"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->标签<!--]--></span></span><!--[--><!--]--></a></div><!--]--></nav><div class="appearance"><span>Appearance</span><span class="xicon-container btn-toggle-dark-mode"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" style="width:20px;height:20px;font-size:20px;color:inherit;"><path d="M15 2h2v3h-2z" fill="currentColor"></path><path d="M27 15h3v2h-3z" fill="currentColor"></path><path d="M15 27h2v3h-2z" fill="currentColor"></path><path d="M2 15h3v2H2z" fill="currentColor"></path><path d="M5.45 6.884l1.414-1.415l2.121 2.122l-1.414 1.414z" fill="currentColor"></path><path d="M23 7.58l2.121-2.12l1.414 1.414l-2.121 2.121z" fill="currentColor"></path><path d="M23.002 24.416l1.415-1.414l2.12 2.122l-1.413 1.414z" fill="currentColor"></path><path d="M5.47 25.13L7.59 23L9 24.42l-2.12 2.12l-1.41-1.41z" fill="currentColor"></path><path d="M16 8a8 8 0 1 0 8 8a8 8 0 0 0-8-8zm0 14a6 6 0 0 1 0-12z" fill="currentColor"></path></svg></span></div></div><div class="series-mask"></div><aside class="series-container"><div class="site-brand"><img class="logo" src="/logo.png" alt="FYJ"><a href="/" class="site-name can-hide">FYJ</a></div><!--[--><!--]--></aside><!--[--><main class="page-container"><h1 class="page-title">浏览器渲染原理</h1><div class="page-info"><span class="xicon-container left"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:18px;height:18px;font-size:18px;color:inherit;"><path d="M16 4a5 5 0 1 1-5 5a5 5 0 0 1 5-5m0-2a7 7 0 1 0 7 7a7 7 0 0 0-7-7z" fill="currentColor"></path><path d="M26 30h-2v-5a5 5 0 0 0-5-5h-6a5 5 0 0 0-5 5v5H6v-5a7 7 0 0 1 7-7h6a7 7 0 0 1 7 7z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->fyj<!--]--></span></span><span class="xicon-container left"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:18px;height:18px;font-size:18px;color:inherit;"><path d="M26 4h-4V2h-2v2h-8V2h-2v2H6c-1.1 0-2 .9-2 2v20c0 1.1.9 2 2 2h20c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 22H6V12h20v14zm0-16H6V6h4v2h2V6h8v2h2V6h4v4z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->2023/05/03<!--]--></span></span><span class="xicon-container left"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:18px;height:18px;font-size:18px;color:inherit;"><path d="M11.17 6l3.42 3.41l.58.59H28v16H4V6h7.17m0-2H4a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h24a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2H16l-3.41-3.41A2 2 0 0 0 11.17 4z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->javascript-note<!--]--></span></span><span class="xicon-container left"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:18px;height:18px;font-size:18px;color:inherit;"><path d="M10 14a4 4 0 1 1 4-4a4.005 4.005 0 0 1-4 4zm0-6a2 2 0 1 0 1.998 2.004A2.002 2.002 0 0 0 10 8z" fill="currentColor"></path><path d="M16.644 29.415L2.586 15.354A2 2 0 0 1 2 13.941V4a2 2 0 0 1 2-2h9.941a2 2 0 0 1 1.414.586l14.06 14.058a2 2 0 0 1 0 2.828l-9.943 9.943a2 2 0 0 1-2.829 0zM4 4v9.942L18.058 28L28 18.058L13.942 4z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->重学<!--]--></span></span><!----></div><div class="theme-reco-default-content"><div><p>袁进老师前端大师课笔记</p><h2 id="浏览器是如何渲染页面的" tabindex="-1"><a class="header-anchor" href="#浏览器是如何渲染页面的" aria-hidden="true">#</a> 浏览器是如何渲染页面的？</h2><p>当浏览器的网络线程收到 HTML 文档后，会产生一个渲染任务，并将其传递给渲染主线程的消息队列。</p><p>在事件循环机制的作用下，渲染主线程取出消息队列中的渲染任务，开启渲染流程。</p><p><img src="/javascriptImages/renderTime.png" alt=""></p><hr><p>整个渲染流程分为多个阶段，分别是： HTML 解析、样式计算、布局、分层、绘制、分块、光栅化、画</p><p>每个阶段都有明确的输入输出，上一个阶段的输出会成为下一个阶段的输入。</p><p>这样，整个渲染流程就形成了一套组织严密的生产流水线。</p><p><img src="/javascriptImages/production.png" alt=""></p><hr><h3 id="_1-渲染的第一步是解析-html-parse-html" tabindex="-1"><a class="header-anchor" href="#_1-渲染的第一步是解析-html-parse-html" aria-hidden="true">#</a> 1.渲染的第一步是<code>解析 HTML （Parse HTML）</code></h3><p>解析过程中遇到 CSS 解析 CSS，遇到 JS 执行 JS。为了提高解析效率，浏览器在开始解析前，会启动一个预解析的线程，率先下载 HTML 中的外部 CSS 文件和 外部的 JS 文件。</p><p>如果主线程解析到<code>link</code>位置，此时外部的 CSS 文件还没有下载解析好，主线程不会等待，继续解析后续的 HTML。这是因为下载和解析 CSS 的工作是在预解析线程中进行的。这就是 CSS 不会阻塞 HTML 解析的根本原因。</p><p><img src="/javascriptImages/cssParse.png" alt=""></p><p>如果主线程解析到<code>script</code>位置，会停止解析 HTML，转而等待 JS 文件下载好，并将全局代码解析执行完成后，才能继续解析 HTML。这是因为 JS 代码的执行过程可能会修改当前的 DOM 树，所以 DOM 树的生成必须暂停。这就是 JS 会阻塞 HTML 解析的根本原因。</p><p><img src="/javascriptImages/jsParse.png" alt=""></p><p>第一步完成后，会得到 DOM 树和 CSSOM 树，浏览器的默认样式、内部样式、外部样式、行内样式均会包含在 CSSOM 树中。</p><p><img src="/javascriptImages/parseHtml.png" alt=""></p><p><img src="/javascriptImages/parsecss.png" alt=""></p><p><img src="/javascriptImages/domCssTree.png" alt=""></p><hr><h3 id="_2-渲染的下一步是样式计算-recalculate-style" tabindex="-1"><a class="header-anchor" href="#_2-渲染的下一步是样式计算-recalculate-style" aria-hidden="true">#</a> 2.渲染的下一步是<code>样式计算（Recalculate Style）</code></h3><p>主线程会遍历得到的 DOM 树，依次为树中的每个节点计算出它最终的样式，称之为 Computed Style。</p><p>在这一过程中，很多预设值会变成绝对值，比如<code>red</code>会变成<code>rgb(255,0,0)</code>；相对单位会变成绝对单位，比如<code>em</code>会变成<code>px</code>。</p><p>这一步完成后，会得到一棵带有样式的 DOM 树。</p><p><img src="/javascriptImages/recalculateStyle.png" alt=""></p><hr><h3 id="_3-接下来是布局-布局-layout-完成后会得到布局树" tabindex="-1"><a class="header-anchor" href="#_3-接下来是布局-布局-layout-完成后会得到布局树" aria-hidden="true">#</a> 3.接下来是<strong>布局</strong>，<code>布局（Layout）</code>完成后会得到布局树</h3><p><img src="/javascriptImages/layoutRes.png" alt=""></p><p>布局阶段会依次遍历 DOM 树的每一个节点，计算每个节点的几何信息。例如节点的宽高、相对包含块的位置。</p><p>大部分时候，DOM 树和布局树并非一一对应。</p><p>比如<code>display:none</code>的节点没有几何信息，因此不会生成到布局树.</p><p><img src="/javascriptImages/Layout.png" alt=""></p><p>又比如使用了伪元素选择器，虽然 DOM 树中不存在这些伪元素节点，但它们拥有几何信息，所以会生成到布局树中。</p><p><img src="/javascriptImages/Layout2.png" alt=""></p><p>还有匿名行盒、匿名块盒等等都会导致 DOM 树和布局树无法一一对应。下图Layout的b应该再包括一个匿名行盒，因为内容必须在行盒中 行盒和块盒不能相邻。</p><p><img src="/javascriptImages/Layout3.png" alt=""></p><hr><h3 id="_4-下一步是分层-layer" tabindex="-1"><a class="header-anchor" href="#_4-下一步是分层-layer" aria-hidden="true">#</a> 4.下一步是<code>分层（Layer）</code></h3><p>主线程会使用一套复杂的策略对整个布局树中进行分层。</p><p>分层的好处在于，将来某一个层改变后，仅会对该层进行后续处理，从而提升效率。</p><p>滚动条、堆叠上下文、transform、opacity 等样式都会或多或少的影响分层结果，也可以通过<code>will-change</code>属性更大程度的影响分层结果。</p><p><img src="/javascriptImages/layer.png" alt=""></p><hr><h3 id="_5-再下一步是绘制-paint" tabindex="-1"><a class="header-anchor" href="#_5-再下一步是绘制-paint" aria-hidden="true">#</a> 5.再下一步是<code>绘制（Paint）</code></h3><p>主线程会为每个层单独产生绘制指令集，用于描述这一层的内容该如何画出来。</p><p><img src="/javascriptImages/paint1.png" alt=""></p><p><img src="/javascriptImages/paint2.png" alt=""></p><hr><h3 id="_6-分块-tiling" tabindex="-1"><a class="header-anchor" href="#_6-分块-tiling" aria-hidden="true">#</a> 6.<code>分块 （Tiling）</code></h3><p>完成绘制后，主线程将每个图层的绘制信息提交给合成线程，剩余工作将由合成线程完成。</p><p>合成线程首先对每个图层进行分块，将其划分为更多的小区域。</p><p><img src="/javascriptImages/tiling1.png" alt=""></p><p>它会从线程池中拿取多个线程来完成分块工作。</p><p><img src="/javascriptImages/tiling2.png" alt=""></p><hr><h3 id="_7-分块完成后-进入光栅化-raster-阶段。" tabindex="-1"><a class="header-anchor" href="#_7-分块完成后-进入光栅化-raster-阶段。" aria-hidden="true">#</a> 7.分块完成后，进入<code>光栅化（Raster）</code>阶段。</h3><p>合成线程会将块信息交给 GPU 进程（不是在说显卡是浏览器进程），以极高的速度完成光栅化。</p><p>GPU 进程会开启多个线程来完成光栅化，并且优先处理靠近视口区域的块。</p><p><img src="/javascriptImages/raster.png" alt=""></p><p><img src="/javascriptImages/raster2.png" alt=""></p><p>光栅化的结果，就是一块一块的位图。</p><hr><h3 id="_8-最后一个阶段就是画-draw-了" tabindex="-1"><a class="header-anchor" href="#_8-最后一个阶段就是画-draw-了" aria-hidden="true">#</a> 8.最后一个阶段就是<code>画（Draw）</code>了</h3><p>合成线程拿到每个层、每个块的位图后，生成一个个<code>指引（quad）</code>信息。</p><p>指引会标识出每个位图应该画到屏幕的哪个位置，以及会考虑到旋转、缩放等变形。</p><p><strong>变形发生在合成线程</strong>，与渲染主线程无关，这就是<code>transform</code>效率高的本质原因。</p><p>合成线程会把 quad 提交给 GPU 进程，由 <strong>GPU 进程产生系统调用</strong>，提交给 GPU 硬件，完成最终的屏幕成像。</p><p><img src="/javascriptImages/draw.png" alt=""></p><p><img src="/javascriptImages/finally.png" alt=""></p><blockquote><p>渲染进程：放到一个沙盒里，与操作系统隔离，更加安全，即使有恶意病毒攻击渲染进程，也不会影响到本机。</p><ul><li>渲染主线程</li><li>合成线程</li></ul></blockquote><h2 id="什么是-reflow" tabindex="-1"><a class="header-anchor" href="#什么是-reflow" aria-hidden="true">#</a> 什么是 reflow？</h2><ul><li>reflow 的本质就是重新计算 layout 树。</li><li>当进行了会影响布局树的操作后，需要重新计算布局树，会引发 layout。</li><li>为了避免连续的多次操作导致布局树反复计算，浏览器会合并这些操作，当 JS 代码全部完成后再进行统一计算。所以，<strong>改动属性造成的 reflow 是异步完成的</strong>。</li><li>也同样因为如此，当 JS 获取布局属性时，就可能造成无法获取到最新的布局信息。</li><li>浏览器在反复权衡下，最终决定获取属性立即 reflow。</li></ul><p><img src="/javascriptImages/reflow.png" alt=""></p><h2 id="什么是-repaint" tabindex="-1"><a class="header-anchor" href="#什么是-repaint" aria-hidden="true">#</a> 什么是 repaint？</h2><ul><li>repaint 的本质就是重新根据分层信息计算了绘制指令。</li><li>当改动了可见样式后，就需要重新计算，会引发 repaint。</li><li>由于元素的布局信息也属于可见样式，所以 reflow 一定会引起 repaint。</li></ul><p><img src="/javascriptImages/repaint.png" alt=""></p><h2 id="为什么-transform-的效率高" tabindex="-1"><a class="header-anchor" href="#为什么-transform-的效率高" aria-hidden="true">#</a> 为什么 transform 的效率高？</h2><p>因为 transform 既不会影响布局也不会影响绘制指令，它影响的只是渲染流程的最后一个<code>draw</code>阶段。</p><p>由于 draw 阶段在合成线程中，所以 transform 的变化几乎不会影响渲染主线程。反之，渲染主线程无论如何忙碌，也不会影响 transform 的变化。</p><p>下面这段代码能够很好的演示这个情况：</p><div class="language-html line-numbers-mode" data-ext="html"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>style</span><span class="token punctuation">&gt;</span></span><span class="token style"><span class="token language-css">
  <span class="token selector">.ball</span> <span class="token punctuation">{</span>
    <span class="token property">width</span><span class="token punctuation">:</span> 100px<span class="token punctuation">;</span>
    <span class="token property">height</span><span class="token punctuation">:</span> 100px<span class="token punctuation">;</span>
    <span class="token property">background</span><span class="token punctuation">:</span> #f40<span class="token punctuation">;</span>
    <span class="token property">border-radius</span><span class="token punctuation">:</span> 50%<span class="token punctuation">;</span>
    <span class="token property">margin</span><span class="token punctuation">:</span> 30px<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">.ball1</span> <span class="token punctuation">{</span>
    <span class="token property">animation</span><span class="token punctuation">:</span> move1 1s alternate infinite ease-in-out<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">.ball2</span> <span class="token punctuation">{</span>
    <span class="token property">position</span><span class="token punctuation">:</span> fixed<span class="token punctuation">;</span>
    <span class="token property">left</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
    <span class="token property">animation</span><span class="token punctuation">:</span> move2 1s alternate infinite ease-in-out<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token atrule"><span class="token rule">@keyframes</span> move1</span> <span class="token punctuation">{</span>
    <span class="token selector">to</span> <span class="token punctuation">{</span>
      <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">translate</span><span class="token punctuation">(</span>100px<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
  <span class="token atrule"><span class="token rule">@keyframes</span> move2</span> <span class="token punctuation">{</span>
    <span class="token selector">to</span> <span class="token punctuation">{</span>
      <span class="token property">left</span><span class="token punctuation">:</span> 100px<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>style</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>btn<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>死循环<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>ball ball1<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>ball ball2<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
    <span class="token keyword">function</span> <span class="token function">delay</span><span class="token punctuation">(</span><span class="token parameter">duration</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">var</span> start <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token keyword">while</span> <span class="token punctuation">(</span>Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> start <span class="token operator">&lt;</span> duration<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    btn<span class="token punctuation">.</span><span class="token function-variable function">onclick</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token function">delay</span><span class="token punctuation">(</span><span class="token number">5000</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></div></div><footer class="page-meta"><div class="meta-item edit-link"><span class="xicon-container left meta-item-label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:20px;height:20px;font-size:20px;color:inherit;"><path d="M2 26h28v2H2z" fill="currentColor"></path><path d="M25.4 9c.8-.8.8-2 0-2.8l-3.6-3.6c-.8-.8-2-.8-2.8 0l-15 15V24h6.4l15-15zm-5-5L24 7.6l-3 3L17.4 7l3-3zM6 22v-3.6l10-10l3.6 3.6l-10 10H6z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->Edit this page<!--]--></span></span></div><div class="meta-item last-updated"><span class="xicon-container left meta-item-label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:20px;height:20px;font-size:20px;color:inherit;"><path d="M26 4h-4V2h-2v2h-8V2h-2v2H6c-1.1 0-2 .9-2 2v20c0 1.1.9 2 2 2h20c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 22H6V12h20v14zm0-16H6V6h4v2h2V6h8v2h2V6h4v4z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->Last Updated 2023/5/4 09:38:58<!--]--></span></span></div></footer><!----><!----></main><!--]--><div class="page-catalog-container"><h5 class="tip">ON THIS PAGE</h5><ul><!--[--><!--[--><li class="page-catalog-menu-depth_2"><a aria-current="page" href="/blogs/javascript-note/liulanqixuanranyuanli.html#浏览器是如何渲染页面的" class="router-link-active router-link-exact-active link page-catalog-item" aria-label="浏览器是如何渲染页面的？"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->浏览器是如何渲染页面的？<!--]--></span></span><!--[--><!--]--></a></li><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/javascript-note/liulanqixuanranyuanli.html#_1-渲染的第一步是解析-html-parse-html" class="router-link-active router-link-exact-active link page-catalog-item" aria-label="1.渲染的第一步是解析 HTML （Parse HTML）"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.渲染的第一步是解析 HTML （Parse HTML）<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/javascript-note/liulanqixuanranyuanli.html#_2-渲染的下一步是样式计算-recalculate-style" class="router-link-active router-link-exact-active link page-catalog-item" aria-label="2.渲染的下一步是样式计算（Recalculate Style）"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->2.渲染的下一步是样式计算（Recalculate Style）<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/javascript-note/liulanqixuanranyuanli.html#_3-接下来是布局-布局-layout-完成后会得到布局树" class="router-link-active router-link-exact-active link page-catalog-item" aria-label="3.接下来是布局，布局（Layout）完成后会得到布局树"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->3.接下来是布局，布局（Layout）完成后会得到布局树<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/javascript-note/liulanqixuanranyuanli.html#_4-下一步是分层-layer" class="router-link-active router-link-exact-active link page-catalog-item" aria-label="4.下一步是分层（Layer）"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->4.下一步是分层（Layer）<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/javascript-note/liulanqixuanranyuanli.html#_5-再下一步是绘制-paint" class="router-link-active router-link-exact-active link page-catalog-item" aria-label="5.再下一步是绘制（Paint）"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->5.再下一步是绘制（Paint）<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/javascript-note/liulanqixuanranyuanli.html#_6-分块-tiling" class="router-link-active router-link-exact-active link page-catalog-item" aria-label="6.分块 （Tiling）"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->6.分块 （Tiling）<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/javascript-note/liulanqixuanranyuanli.html#_7-分块完成后-进入光栅化-raster-阶段。" class="router-link-active router-link-exact-active link page-catalog-item" aria-label="7.分块完成后，进入光栅化（Raster）阶段。"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->7.分块完成后，进入光栅化（Raster）阶段。<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/javascript-note/liulanqixuanranyuanli.html#_8-最后一个阶段就是画-draw-了" class="router-link-active router-link-exact-active link page-catalog-item" aria-label="8.最后一个阶段就是画（Draw）了"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->8.最后一个阶段就是画（Draw）了<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--]--><!--[--><li class="page-catalog-menu-depth_2"><a aria-current="page" href="/blogs/javascript-note/liulanqixuanranyuanli.html#什么是-reflow" class="router-link-active router-link-exact-active link page-catalog-item" aria-label="什么是 reflow？"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->什么是 reflow？<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_2"><a aria-current="page" href="/blogs/javascript-note/liulanqixuanranyuanli.html#什么是-repaint" class="router-link-active router-link-exact-active link page-catalog-item" aria-label="什么是 repaint？"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->什么是 repaint？<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_2"><a aria-current="page" href="/blogs/javascript-note/liulanqixuanranyuanli.html#为什么-transform-的效率高" class="router-link-active router-link-exact-active link page-catalog-item" aria-label="为什么 transform 的效率高？"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->为什么 transform 的效率高？<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--]--></ul></div></div></div></div><!----><!----><!--]--></div>
    <script type="module" src="/assets/app-5e55c3a9.js" defer></script>
  </body>
</html>
